package com.acargil.sudoku.view;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;

import javax.swing.JPanel;

import com.acargil.sudoku.model.ISudokuEngine;

/**
 * @author Oguzhan 
 * */
public class BoardPanel  extends JPanel {

	private static final long serialVersionUID = 7237126252080571301L;
	
	private ISudokuEngine model;
	
	private static final int CELL_PIXELS = 50;  // Size of each cell.
    private static final int PUZZLE_SIZE = 9;   // Number of rows/cols
    private static final int SUBSQUARE   = 3;   // Size of subsquare.
    private static final int BOARD_PIXELS = CELL_PIXELS * PUZZLE_SIZE;
    private static final int TEXT_OFFSET = 15;  // Fine tuning placement of text.
    private static final Font TEXT_FONT  = new Font("Sansserif", Font.BOLD, 24);
   
    private int selectionXCoordinate = 0, selectionYCoordinate = 0;
    
    public BoardPanel() {
        setPreferredSize(new Dimension(BOARD_PIXELS + 2, BOARD_PIXELS + 2));
        setBackground(Color.WHITE);
        this.selectionXCoordinate = 0;
        this.selectionYCoordinate = 0;
    }

    @Override
    public void paintComponent(Graphics g) {
    
        g.setColor(getBackground());
        g.fillRect(0, 0, getWidth(), getHeight());
        g.setColor(Color.BLACK);

        drawSelectedCell(g);
        drawGridLines(g);
        drawCellValues(g);
    }

    /**
     * This method draws grid lines of SUDOKU puzzle, successfully.
     * */
    private void drawGridLines(Graphics g) {

        int acrossOrDown;

        //... Draw grid lines.  Terminates on <= to get final line.
        for (int i = 0; i <= PUZZLE_SIZE; i++) {
            acrossOrDown = i * CELL_PIXELS;
            //... Draw at different x's from y=0 to y=BOARD_PIXELS.
            g.drawLine(acrossOrDown, 0, acrossOrDown, BOARD_PIXELS);
            //... Draw at different y's from x=0 to d=BOARD_PIXELS.
            g.drawLine(0, acrossOrDown, BOARD_PIXELS, acrossOrDown);

            //... Draw a double line for subsquare boundaries.
            if (i % SUBSQUARE == 0) {
                acrossOrDown++;  // Move one pixel and redraw as above
                g.drawLine(acrossOrDown, 0, acrossOrDown, BOARD_PIXELS);
                g.drawLine(0, acrossOrDown, BOARD_PIXELS, acrossOrDown);
            }
        }
    }

    /**
     * Draw values of cells to the grid view. 
     * <code>AbstractSudokuModel.getCell(x,y)</code> supplies the values. 
     * */
    private void drawCellValues(Graphics g) {
        int xDisplacement, yDisplacement, value;
        g.setFont(TEXT_FONT);
        for (int x = 0; x < PUZZLE_SIZE; x++) {
            yDisplacement = (x+1) * CELL_PIXELS - TEXT_OFFSET;
            for (int y = 0; y < PUZZLE_SIZE; y++) {
                value = model.getCellValue(y, x);
                if (value != ISudokuEngine.EMPTY_VALUE) {
                    xDisplacement = y * CELL_PIXELS + TEXT_OFFSET;
                    g.drawString("" + value, xDisplacement, yDisplacement);
                }
            }
        }
    }

    private void drawSelectedCell(Graphics g) {
        int x;
        int y;
        x = (this.selectionXCoordinate / CELL_PIXELS) * CELL_PIXELS;
        y = (this.selectionYCoordinate / CELL_PIXELS) * CELL_PIXELS;
        g.drawRoundRect(x+1, y+1, CELL_PIXELS-2, CELL_PIXELS-2,10,10);
        g.drawRoundRect(x+2, y+2, CELL_PIXELS-4, CELL_PIXELS-4,10,10);
        g.drawRoundRect(x+3, y+3, CELL_PIXELS-6, CELL_PIXELS-6,10,10);
//        g.drawImage(SELECTION_IMAGE, x, y, Color.yellow, this);
    }

    protected void shiftSelection(int direction) {
        if (direction == ISudokuView.SHIFT_DOWN) {
            if (!(this.selectionYCoordinate >= 400)) {
                this.selectionYCoordinate += CELL_PIXELS;
            }
        }
        else if (direction == ISudokuView.SHIFT_LEFT) {
            if (this.selectionXCoordinate >= 50) {
                this.selectionXCoordinate -= CELL_PIXELS;
            }
        }
        else if (direction == ISudokuView.SHIFT_RIGHT) {
            if (!(this.selectionXCoordinate >= 400)) {
                this.selectionXCoordinate += CELL_PIXELS;
            }
        }
        else if (direction == ISudokuView.SHIFT_UP) {
            if (this.selectionYCoordinate >= 50) {
                this.selectionYCoordinate -= CELL_PIXELS;
            }
        }
        
        repaint();
    }

    protected int getSelectionXCoordinate() {
        return selectionXCoordinate / CELL_PIXELS;
    }

    protected int getSelectionYCoordinate() {
        return selectionYCoordinate / CELL_PIXELS;
    }

    protected void setSelectionCoordinates(int x, int y) {
        this.selectionXCoordinate = x;
        this.selectionYCoordinate = y;
        repaint();
    }

    protected int getCellSize() {
        return BoardPanel.CELL_PIXELS;
    }

    protected void clearAllCells() {
        repaint();
    }
}
